//
//  ByCoreCacheUserDefaults.m
//  beibei_ios
//
//  Created by hebidu on 16/4/16.
//  Copyright © 2016年 hebidu. All rights reserved.
//

#import "ByCoreCacheUserDefaults.h"

@implementation ByCoreCacheUserDefaults

static ByCoreCacheUserDefaults *instance = nil;

/** 单例实现 */
+ (instancetype)shareInstance {
    static dispatch_once_t onceToken;
    // 这个函数中的代码快任务只能执行一次，他是线程安全的。
    dispatch_once(&onceToken, ^{
        instance = [[[self class] alloc] init];
    });
    return instance;
}
/** 实现一些限制方法，限制这个类始终只能创建一个对象，并且此对象不能销毁 */
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    
    if (instance == nil) {
        instance = [super allocWithZone:zone];
    }
    return instance;
}


-(void) setObject:(NSString *) key :(NSObject *) value :(double ) seconds{
    
    

}

/** 存贮值 */
/** value 值 如果等于nil，将清除该缓存
    stamp 缓存时间，单位（秒） 
 */
- (void)setObject:(id)value key:(NSString *)key stamp:(CGFloat)stamp {
    
    /** 存贮值为空则清楚缓存 */
    if (value == nil) {
        [self clearForKey:key];
        return ;
    }
    
    /** 自定义的变量如果实现NSCoder协议，则可以变成NSData存贮 */
    if ([value respondsToSelector:@selector(encodeWithCoder:)]) {
        NSData *customData = [NSKeyedArchiver archivedDataWithRootObject:value];
        [[NSUserDefaults standardUserDefaults] setObject:customData forKey:[self getKey:key]];
    }else{
        [[NSUserDefaults standardUserDefaults] setObject:value forKey:[self getKey:key]];
    }
    
    /** 存储过期时间到特定的时间键中 */
    CGFloat expireTime = stamp + [NSDate currentDateTimeInterval];
    [[NSUserDefaults standardUserDefaults] setDouble:expireTime forKey:[self getExpireTimeKey:key]];
    
    [[NSUserDefaults standardUserDefaults] synchronize];
}


/** 获取值 */
- (NSObject *)getValueWithKey:(NSString *)key {
    
    NSTimeInterval currentTimeStamp = [NSDate currentDateTimeInterval];
    
    double expire_time = [[NSUserDefaults standardUserDefaults] doubleForKey:[self getExpireTimeKey:key]];
    
    /** 已经过期则返回nil，并清除缓存 */
    if(expire_time < currentTimeStamp){
        [self clearForKey:key];
        return nil;
    }
    
    id object =  [[NSUserDefaults standardUserDefaults] objectForKey:[self getKey:key]];
    if (object != nil
        && [object respondsToSelector:@selector(initWithCoder:)]
        && [object isKindOfClass:NSData.class]) {
        
        NSData *customData = (NSData *)object;
        
        return [NSKeyedUnarchiver unarchiveObjectWithData:customData];
    }
    
    return object;

}

/** 清除所有缓存值 */
- (void)clear{
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSDictionary *dict = [userDefaults dictionaryRepresentation];
    
    for (id key in dict) {
        if([key isKindOfClass:[NSString class]]){
            
            NSString *strKey = (NSString *)key;
            
            if ([strKey hasPrefix:BY_CACHE_PREFIX] ){
                // 只删除 含前缀的值
                [userDefaults removeObjectForKey:key];
            }
        }
    }
    
    [userDefaults synchronize];
}

/** 清除某个键名的缓存 */
- (void)clearForKey:(NSString *)key{
    
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:[self getKey:key]];
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:[self getExpireTimeKey:key]];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

#pragma mark - private方法

/** 生成包含前缀的键名 */
- (NSString *)getKey:(NSString *)key {
    return [[NSString alloc] initWithFormat:@"%@%@", BY_CACHE_PREFIX ,key];
}

/** 生成包含前缀的过期时间键名 */
- (NSString * )getExpireTimeKey:(NSString *)key {  
    return [[NSString alloc] initWithFormat:@"%@expire_%@", BY_CACHE_PREFIX ,key];
}


@end
